package com.dommettj.rawfix.gui;

import com.dommettj.rawfix.gui.event.GuiEventCallback;
import com.dommettj.rawfix.gui.event.GuiEventHandler;
import com.dommettj.rawfix.message.*;
import com.dommettj.rawfix.session.NioSession;
import com.dommettj.rawfix.session.Session;
import com.dommettj.rawfix.session.SessionException;
import com.dommettj.rawfix.settings.FileBasedSettings;
import com.dommettj.rawfix.settings.FileProviderImpl;
import com.dommettj.rawfix.settings.Settings;
import com.dommettj.rawfix.utils.SystemClock;
import org.apache.log4j.Logger;

import java.io.IOException;

public class RawFixGui implements GuiEventHandler, MessageHandler {

    private static final Logger logger = Logger.getLogger(RawFixGui.class);
    private static final String PROPERTIES_FILENAME = "rawfix.properties";

    private final RawFixMainFrame frame;
    private final GuiEventCallback eventCallback;
    private final Session session;

    public RawFixGui(final Session session, final Settings settings) throws IOException {

        frame = new RawFixMainFrame(settings);

        this.session = session;
        this.eventCallback = frame.getEventCallback();
        frame.registerEventHandler(this);
        this.session.registerMessageHandler(MessageType.LOGON, this);
        this.session.registerMessageHandler(MessageType.LOGOFF, this);
        this.session.registerMessageHandler(MessageType.HEARTBEAT, this);
    }

    public void show() {
        frame.setVisible(true);
    }

    @Override
    public void logon() {

        logger.debug("Logging on");

        try {
            session.start();
        } catch (SessionException e) {
            eventCallback.logonFailure(e.getMessage());
        } catch (IOException e) {
            eventCallback.logonFailure(e.getMessage());
        }
    }

    @Override
    public void logoff() {

        logger.debug("Logging off");
        try {
            session.stop();

        } catch (Exception e) {
            eventCallback.logoffFailure(e.getMessage());
        }
    }

    @Override
    public void sendMessage(String message) {

        try {
            session.sendMessage(session.constructMessage(message));
        } catch (MalformedMessageException e) {
            eventCallback.messageSendFailure("[" + message + "], Reason [Message is malformed]");
        } catch (SessionException e) {
            eventCallback.messageSendFailure("[" + message + "], Reason [" + e.getMessage() + "]");
        }
    }

    @Override
    public void settingsUpdated(Settings settings) {
        session.notifySessionSettingsUpdated(settings);
    }

    @Override
    public void close() {
        if(session.isActive()) {
            logger.debug("Stopping session");
            try {
                session.stop();
            } catch (Exception e) {
                logger.error("Failed to stop session", e);
            }
        }
    }

    @Override
    public void handle(String message) {
        try {
            eventCallback.messageReceived(MessageUtils.getMessageType(message), message);
        } catch (UnknownMessageTypeException e) {
            logger.error("Failed to handle message", e);
        }
    }

    public static void main(String[] args) throws IOException {

        final Settings settings = new FileBasedSettings(new FileProviderImpl(), PROPERTIES_FILENAME);
        final Session session = new NioSession(settings.loadHost(), Integer.parseInt(settings.loadPort()),
                                               new FixMessageGenerator(new SystemClock(), "FIX.4.4", settings.loadSenderCompId(), settings.loadTargetCompId()));

        final RawFixGui gui = new RawFixGui(session, settings);
        gui.show();
    }
}
